package com.qd.p2p.web.action;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.FileUtils;
import org.apache.log4j.Logger;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.convention.annotation.Action;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.qdlc.p2p.biz.util.UserLoginUtil;
import com.qdlc.p2p.biz.web.action.BaseAction;
import com.qdlc.p2p.common.constant.BorrowStyle;
import com.qdlc.p2p.common.exception.UserException;
import com.qdlc.p2p.common.util.BigDecimalUtil;
import com.qdlc.p2p.common.util.DateUtil;
import com.qdlc.p2p.common.util.ImageUtil;
import com.qdlc.p2p.common.util.MessageUtil;
import com.qdlc.p2p.common.util.StringUtil;
import com.qdlc.p2p.common.util.ValidateUtil;
import com.qdlc.p2p.dal.dto.User;
import com.qdlc.p2p.dal.model.CalculatorModel;
import com.qdlc.p2p.dal.model.interest.EachPlan;
import com.qdlc.p2p.dal.model.interest.InstallmentRepaymentCalculator;
import com.qdlc.p2p.dal.model.interest.InterestCalculator;
import com.qdlc.p2p.dal.model.interest.MonthlyInterestCalculator;
import com.qdlc.p2p.dal.model.interest.OnetimeRepaymentCalculator;

/**
 * 工具类Action,验证码、生产图、计算器
 *
 * @author fuxingxing
 */
public class ToolAction extends BaseAction {
    private static Logger logger = Logger.getLogger(ToolAction.class);

    private String userId;
    private String size;

    private double account;
    private double lilv;
    private int times;
    private int time_limit_day;
    private String type;

    private File upload;
    private File localUrl;
    private String uploadFileName;
    private String sep = File.separator;

    // 裁剪后的图像大小
    private double cropX;
    private double cropY;
    private double cropW;
    private double cropH;

    private String plugintype;

    /**
     * 验证码
     *
     * @return
     * @throws Exception
     */
    @Action("/validimg")
    public String validimg() throws Exception {
        genernateCaptchaImage();
        return null;
    }

    /**
     * 异步校验验证码
     *
     * @return
     * @throws Exception
     */
    @Action("/valicode")
    public String valicode() throws Exception {
        String valicode = paramString("valicode");
        Map<String, Object> data = new HashMap<String, Object>();
        if (StringUtil.isBlank(valicode) || !ValidateUtil.checkValidCode(valicode)) {
            throw new UserException("验证码错误!", 1);
        }
        data.put("result", true);
        data.put("msg", "验证码正确!");
        printWebJson(getStringOfJpaObj(data));
        return null;
    }

    /**
     * 动态输出图像Action
     *
     * @return
     * @throws Exception
     */
    @Action("/imgurl")
    public String imgurl() throws Exception {
        if (StringUtil.toInt(userId) < 1) {
            userId = StringUtil.toInt(userId) + "";
        }
        userId = (userId == null || userId.equals("")) ? "" : userId;
        size = (size == null || size.equals("")) ? "" : size;
        String[] sizes = {"big", "middle", "small"};
        List<String> sizelist = Arrays.asList(sizes);
        size = sizelist.contains(size) ? size : "big";

        String url = "data" + sep + "avatar" + sep + userId + "_avatar_" + size + ".jpg";
        String contextPath = ServletActionContext.getServletContext().getRealPath("/");
        if (contextPath.lastIndexOf(sep) < contextPath.length() - 1) {
            contextPath += sep;
        }
        url = contextPath + url;
        File avatarFile = new File(url);
        if (!avatarFile.exists()) {
            url = contextPath + "data" + sep + "avatar" + sep + "noavatar_" + size + ".gif";
        }
        String urlFile = contextPath + "data" + sep + "avatar" + sep;
        File file = new File(urlFile);
        if (!file.exists()) {
            file.mkdirs();
        }
        logger.debug("IMG_URL:" + url);
        createImg(url);
        return null;
    }

    public String editorUploadImg() throws Exception {
        String newFileName = "";
        String retMsg = "";
        if (upload == null) {
            retMsg = getRetMsg(1, "上传图片失败！", "");
        }
        if (retMsg.isEmpty()) {
            String imgUrl = upload(upload, uploadFileName, "/data/upload", newFileName + ".jpg");
            retMsg = getRetMsg(0, "上传图片成功！", imgUrl);
        }

        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        out.print(retMsg);
        out.flush();
        out.close();
        return null;
    }

    @Action("/uploadImg")
    public void uploadImg() throws Exception {
        String url = ServletActionContext.getServletContext().getRealPath("/") + "/data/upfiles/images/";
        File url_file = new File(url);
        if (!url_file.exists()) {
            url_file.mkdir();
        }
        String file_name = System.currentTimeMillis() + ".jpg";
        File imgFile = new File(url + file_name);
        FileUtils.copyFile(upload, imgFile);
        response.getWriter().print(JSONArray.toJSON(file_name));
    }

    private String getRetMsg(int flag, String msg, String imgUrl) {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("error", flag);
        map.put("message", msg);
        map.put("url", request.getContextPath() + imgUrl);
        return JSON.toJSONString(map);
    }

    /**
     * 图片上传
     *
     * @return
     * @throws Exception
     */
    public String upload() throws Exception {
        Map map = ServletActionContext.getContext().getSession();
        User user = UserLoginUtil.getLoginUser();
        logger.debug("文件：" + this.upload);
        logger.debug("文件名：" + uploadFileName);
        String destFilename2 = ServletActionContext.getServletContext().getRealPath("/data") + sep + "temp" + sep
                + user.getUserId() + ".jpg";
        logger.debug(destFilename2);
        File imageFile2 = null;
        try {
            imageFile2 = new File(destFilename2);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
        }
        HttpServletResponse response = ServletActionContext.getResponse();
        HttpServletRequest request = ServletActionContext.getRequest();
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        String retMsg = "";
        if (!ImageUtil.fileIsImage(upload)) {
            retMsg = getRetMsg(1, "您上传的图片无效，请重新上传！", "");
            out.print(retMsg);
            out.flush();
            out.close();
            return null;
        }
        FileUtils.copyFile(upload, imageFile2);

        // 保存上传的临时图片名称
        String src = request.getContextPath() + "/data/temp/" + user.getUserId() + ".jpg";
        BufferedImage srcImage = null;
        BufferedImage destImage = null;
        File file = new File(destFilename2);
        int newWi = 0;
        int newHi = 0;
        try {
            srcImage = ImageIO.read(file);
            int w = srcImage.getWidth();
            int h = srcImage.getHeight();
            int minW = (w > h) ? w : h;
            double newWd = (300.0 / minW) * w;
            double newHd = (300.0 / minW) * h;
            newWi = (int) newWd;
            newHi = (int) newHd;
            destImage = new BufferedImage(newWi, newHi, BufferedImage.TYPE_3BYTE_BGR);
            destImage.getGraphics().drawImage(srcImage.getScaledInstance(newWi, newHi, Image.SCALE_SMOOTH), 0, 0, null);
            ImageIO.write(destImage, "jpg", new File(destFilename2));
        } catch (Exception e) {
            e.printStackTrace();
        }
        logger.debug("Print img:" + src);
        out.print("{");
        out.print("error: '',\n");
        out.print("msg: '" + src + "',\n");
        out.print("width: " + newWi + ",\n");
        out.print("height: " + newHi + "\n");
        out.print("}");
        out.flush();
        out.close();
        return null;
    }

    // 生成需要裁剪的照片
    public String cropimg() throws Exception {
        try {
            Map map = ServletActionContext.getContext().getSession();
            User user = UserLoginUtil.getLoginUser();
            String fileName = ServletActionContext.getServletContext().getRealPath("/data") + sep + "temp" + sep
                    + user.getUserId() + ".jpg";
            logger.info(fileName);
            this.createImg(fileName);
        } catch (Exception e) {
            logger.info(e.getMessage());
            e.printStackTrace();
        }
        return null;
    }

    // 保存头像
    public String saveAvatar() throws Exception {
        try {
            HttpServletResponse response = ServletActionContext.getResponse();
            response.setContentType("application/json;charset=UTF-8");
            int x = 0, y = 0, w = 0, h = 0;
            if (cropX >= 0) {
                x = (int) cropX;
            }
            if (cropY >= 0) {
                y = (int) cropY;
            }
            if (cropW >= 0) {
                w = (int) cropW;
            }
            if (cropH >= 0) {
                h = (int) cropH;
            }

            logger.debug("X=" + x + ",Y=" + y + ",W=" + w + ",H=" + h);
            @SuppressWarnings("unused")
            boolean re = operateImg(x, y, w, h);
            PrintWriter out = response.getWriter();
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("flag", 1);
            map.put("msg", "success");
            map.put("useravatar", "");
            out.print(JSON.toJSON(map));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    private boolean operateImg(int x, int y, int w, int h) throws IOException {
        Map map = ServletActionContext.getContext().getSession();
        User user = UserLoginUtil.getLoginUser();
        String dataPath = ServletActionContext.getServletContext().getRealPath("/data");
        String avatarDir = dataPath + sep + "avatar";
        String dest = avatarDir + sep + user.getUserId() + "_avatar_middle.jpg";
        String smalldest = avatarDir + sep + user.getUserId() + "_avatar_small.jpg";
        String src = ServletActionContext.getServletContext().getRealPath("/data") + sep + "temp" + sep
                + user.getUserId() + ".jpg";
        BufferedImage srcImage = null;
        try {
            srcImage = ImageIO.read(new File(src));
            BufferedImage destImage = srcImage.getSubimage(x, y, w, h);
            BufferedImage lastImage = new BufferedImage(w, h, BufferedImage.TYPE_3BYTE_BGR);
            lastImage.getGraphics().drawImage(destImage, 0, 0, null);
            BufferedImage compressImage = new BufferedImage(98, 98, BufferedImage.TYPE_3BYTE_BGR);
            BufferedImage compressImage48 = new BufferedImage(48, 48, BufferedImage.TYPE_3BYTE_BGR);
            compressImage.getGraphics().drawImage(lastImage.getScaledInstance(98, 98, Image.SCALE_SMOOTH), 0, 0, null);
            compressImage48.getGraphics()
                    .drawImage(lastImage.getScaledInstance(48, 48, Image.SCALE_SMOOTH), 0, 0, null);
            File avatarDirFile = new File(avatarDir);
            if (!avatarDirFile.exists()) {
                avatarDirFile.mkdir();
            }
            File newFile = new File(dest);
            File smallNewFile = new File(smalldest);
            logger.info("Avatar dest:" + dest);
            ImageIO.write(compressImage, "jpg", newFile);
            ImageIO.write(compressImage48, "jpg", smallNewFile);
            FileUtils.forceDelete(new File(src));
        } catch (Exception e) {
            logger.error(e.getMessage());
            return false;
        }
        return true;
    }

    /**
     * 以图片流形式输出
     *
     * @param url
     * @throws IOException
     */
    private void createImg(String url) throws IOException {
        HttpServletResponse res = ServletActionContext.getResponse();
        res.setHeader("Pragma", "No-cache");
        res.setHeader("Cache-Control", "no-cache");
        res.setDateHeader("Expires", 0);
        OutputStream output = res.getOutputStream();// 得到输出流
        if (url.toLowerCase().endsWith(".jpg")) {
            // 表明生成的响应是图片
            res.setContentType("image/jpeg");
        } else if (url.toLowerCase().endsWith(".gif")) {
            res.setContentType("image/gif");
        }
        File file = new File(url);
        if (!file.exists()) {
            url = ServletActionContext.getServletContext().getRealPath("/data") + sep + "avatar" + sep
                    + "noavatar_middle.gif";
        }
        InputStream imageIn = new FileInputStream(new File(url));
        BufferedInputStream bis = new BufferedInputStream(imageIn);// 输入缓冲流
        BufferedOutputStream bos = new BufferedOutputStream(output);// 输出缓冲流
        byte data[] = new byte[4096];// 缓冲字节数
        int size = 0;
        size = bis.read(data);
        while (size != -1) {
            bos.write(data, 0, size);
            size = bis.read(data);
        }
        bis.close();
        bos.flush();// 清空输出缓冲流
        bos.close();
        output.flush();
        output.close();
    }


    /**
     * 显示插件Action
     *
     * @return
     * @throws Exception
     */
    public String plugin() throws Exception {
        HttpServletResponse response = ServletActionContext.getResponse();
        response.setContentType("text/html;charset=UTF-8");
        return null;
    }

    /**
     * 利息计算器 页面
     *
     * @return
     * @throws Exception
     */
    @Action("/tool/interestTool")
    public String interestTool() throws Exception {

        return "interestTool";
    }

    /**
     * 利息计算器
     *
     * @throws Exception
     */
    @Action("/tool/calculator")
    public void calculator() throws Exception {
        // 数据校验
        verifyCalculator();

        // 还款方式
        int type = paramInt("type");

        // 期限类型 1天标 0月标
        int timeType = paramInt("timeType");

        // 期限
        int timeLimit = paramInt("timeLimit");

        // 金额
        double amount = paramDouble("amount");

        // 年化率
        double yearApr = paramDouble("yearApr") / 100;

        // 计息开始时间
        Date date = DateUtil.getNow();

        // 还款利息总额
        double interestTotal = 0;

        // 还款总额（本息）
        double total = 0;

        InterestCalculator ic = null;
        List<EachPlan> list = new ArrayList<EachPlan>();
        List<CalculatorModel> list_ = new ArrayList<CalculatorModel>();
        Map<String, Object> data = new HashMap<String, Object>();

        if (timeType == 1 && type == BorrowStyle.STYLE_ONETIME_REPAYMENT) { // 天标,一次性还款
            ic = new OnetimeRepaymentCalculator(amount, yearApr, date, 1, 0);
        } else if (type == BorrowStyle.STYLE_ONETIME_REPAYMENT) { // 一次性还款
            ic = new OnetimeRepaymentCalculator(amount, yearApr, date, timeLimit, 0);
        } else if (type == BorrowStyle.STYLE_MONTHLY_INTEREST) { // 每月还息到期还本
            ic = new MonthlyInterestCalculator(amount, yearApr, date, timeLimit, true, 0);
        } else if (type == BorrowStyle.STYLE_INSTALLMENT_REPAYMENT) { // 等额本息
            ic = new InstallmentRepaymentCalculator(amount, yearApr, date, timeLimit, 0);
        }
        if (timeType == 1) {
            list = ic.calculator(timeLimit);
        } else {
            list = ic.calculator();
        }
        int i = 0;
        for (EachPlan eachPlan : list) {
            CalculatorModel model = new CalculatorModel();
            model.setCapital(eachPlan.getCapital());
            model.setInterest(eachPlan.getInterest());
            model.setPeriod(i + 1);
            model.setPeriodTotal(eachPlan.getNetTotal());
            model.setRepayTime(eachPlan.getRepayTime());
            double needRepay = eachPlan.getNeedRepay();
            model.setNeedRepay(needRepay);

            list_.add(model);

            //还款总额
            interestTotal += eachPlan.getInterest();
            i++;
        }
        total = BigDecimalUtil.add(interestTotal, amount);
        data.put("data", list_);
        data.put("interestTotal", BigDecimalUtil.round(interestTotal, 2));
        data.put("total", BigDecimalUtil.round(total, 2));
        printWebJson(getStringOfJpaObj(data));
    }

    /**
     * 计算器值校验
     *
     * @return
     */
    private void verifyCalculator() throws Exception {
        // 还款方式
        int type = paramInt("type");

        // 期限类型 1天标 0月标
        int timeType = paramInt("timeType");

        // 期限
        int timeLimit = paramInt("timeLimit");

        // 金额
        double amount = paramDouble("amount");

        // 年化率
        double yearApr = paramDouble("yearApr");

        Map<String, Object> data = new HashMap<String, Object>();
        if (type != BorrowStyle.STYLE_INSTALLMENT_REPAYMENT
                && type != BorrowStyle.STYLE_MONTHLY_INTEREST
                && type != BorrowStyle.STYLE_ONETIME_REPAYMENT) {
            data.put("error", MessageUtil.getMessage("MF103008001"));
            printWebJson(getStringOfJpaObj(data));
            return;
        }

        if (timeType != 1 && timeType != 0) {
            data.put("error", MessageUtil.getMessage("MF103008002"));
            printWebJson(getStringOfJpaObj(data));
            return;
        }

        if (amount <= 0) {
            data.put("error", MessageUtil.getMessage("MF103008003"));
            printWebJson(getStringOfJpaObj(data));
            return;
        }

        if (amount > 10000000) {
            data.put("error", MessageUtil.getMessage("MF103008003"));
            printWebJson(getStringOfJpaObj(data));
            return;
        }

        if ((timeType == 1 && timeLimit > 360)
                || (timeType == 0 && timeLimit > 36)) {
            data.put("error", MessageUtil.getMessage("MF103008005"));
            printWebJson(getStringOfJpaObj(data));
            return;
        }

        if (yearApr > 50) {
            data.put("error", MessageUtil.getMessage("MF103008004"));
            printWebJson(getStringOfJpaObj(data));
            return;
        }
    }

    public String actionNotFound() throws Exception {
        return SUCCESS;
    }

    public String getUserId() {
        return userId;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }

    public String getSize() {
        return size;
    }

    public void setSize(String size) {
        this.size = size;
    }

    public double getAccount() {
        return account;
    }

    public void setAccount(double account) {
        this.account = account;
    }

    public double getLilv() {
        return lilv;
    }

    public void setLilv(double lilv) {
        this.lilv = lilv;
    }

    public int getTimes() {
        return times;
    }

    public void setTimes(int times) {
        this.times = times;
    }

    public int getTime_limit_day() {
        return time_limit_day;
    }

    public void setTime_limit_day(int time_limit_day) {
        this.time_limit_day = time_limit_day;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public File getUpload() {
        return upload;
    }

    public void setUpload(File upload) {
        this.upload = upload;
    }

    public String getUploadFileName() {
        return uploadFileName;
    }

    public void setUploadFileName(String uploadFileName) {
        this.uploadFileName = uploadFileName;
    }

    public double getCropX() {
        return cropX;
    }

    public void setCropX(double cropX) {
        this.cropX = cropX;
    }

    public double getCropY() {
        return cropY;
    }

    public void setCropY(double cropY) {
        this.cropY = cropY;
    }

    public double getCropW() {
        return cropW;
    }

    public void setCropW(double cropW) {
        this.cropW = cropW;
    }

    public double getCropH() {
        return cropH;
    }

    public void setCropH(double cropH) {
        this.cropH = cropH;
    }

    public String getPlugintype() {
        return plugintype;
    }

    public void setPlugintype(String plugintype) {
        this.plugintype = plugintype;
    }

    public File getLocalUrl() {
        return localUrl;
    }

    public void setLocalUrl(File localUrl) {
        this.localUrl = localUrl;
    }

}
